home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug231 / process.c < prev    next >
Text File  |  1987-06-17  |  7KB  |  254 lines

  1. /*
  2.     Little Smalltalk
  3.  
  4.         process manager
  5.         dennis a. vadner and michael t. benhase, 11/84
  6.         modified by timothy a. budd 4/85
  7. */
  8. /*
  9.     The source code for the Little Smalltalk System may be freely
  10.     copied provided that the source of all files is acknowledged
  11.     and that this condition is copied with each file.
  12.  
  13.     The Little Smalltalk System is distributed without responsibility
  14.     for the performance of the program and without any guarantee of
  15.     maintenance.
  16.  
  17.     All questions concerning Little Smalltalk should be addressed to:
  18.  
  19.         Professor Tim Budd
  20.         Department of Computer Science
  21.         Oregon State University
  22.         Corvallis, Oregon
  23.         97331
  24.         USA
  25. */
  26.  
  27. # include "object.h"
  28.  
  29. # include <stdio.h>
  30.  
  31. # ifdef SIGS
  32. # include <signal.h>
  33. # endif
  34.  
  35. # ifdef SETJUMP
  36. # include <setjmp.h>
  37. # endif
  38.  
  39. # include "drive.h"
  40. # include "interp.h"
  41. # include "process.h"
  42.  
  43. extern int  test_driver();    /* routine to test for user keystrokes*/
  44.  
  45. static process  *currentProcess;    /* current process */
  46. static process  *fr_process = 0;    /* process memory free list */
  47.  
  48. int  atomcnt = 0;            /* atomic action flag */
  49. process  *runningProcess;        /* currently running process,
  50.                        may be different from
  51.                        currentProcess during process
  52.                        termination */
  53.  
  54. # define PROCINITMAX 6
  55. static process prcinit[PROCINITMAX];    /* initial process free list */
  56.  
  57.  
  58. /* init_process - initialize the process module */
  59. init_process ()
  60. {    process *p;
  61.     int i;
  62.  
  63.     /* first make the initial process free list */
  64.     for (p = prcinit, i = 0; i < PROCINITMAX; i++, p++) {
  65.         p->next = fr_process;
  66.         fr_process = p;
  67.         }
  68.  
  69.     /* make the process associated with the driver */
  70.     currentProcess = cr_process(o_drive);
  71.     assign(currentProcess->next, currentProcess);
  72.     assign(currentProcess->prev, currentProcess);
  73.     currentProcess->p_state = ACTIVE;
  74. }
  75.  
  76. /* cr_process - create a new process with the given interpreter */
  77. process  *cr_process (anInterpreter)
  78. interpreter  *anInterpreter;
  79. {    process  *new;
  80.  
  81.     if (fr_process) {
  82.         new = (process *) fr_process;
  83.         fr_process = fr_process->next;
  84.         }
  85.     else
  86.         new = structalloc(process);
  87.  
  88.     new->p_ref_count = 0;
  89.     new->p_size = PROCSIZE;
  90.  
  91.     sassign(new->interp, anInterpreter);
  92.     new->p_state = SUSPENDED;
  93.     sassign(new->next, (process *) o_nil);
  94.     sassign(new->prev, (process *) o_nil);
  95.  
  96.     return(new);
  97. }
  98.  
  99.  
  100. /* free_process - return an unused process to free list */
  101. free_process (aProcess)
  102. process  *aProcess;
  103. {
  104.     obj_dec((object *) aProcess->interp);
  105.     obj_dec((object *) aProcess->next);
  106.     obj_dec((object *) aProcess->prev);
  107.     aProcess->p_state = TERMINATED;
  108.     aProcess->next = fr_process;
  109.     fr_process = aProcess;
  110. }
  111.  
  112. /* flush_processes - flush out any remaining process from queue */
  113. flush_processes ()
  114. {
  115.     while (currentProcess != currentProcess->next)
  116.        remove_process(currentProcess);
  117.  
  118.     /* prev link and next link should point to the same place now.
  119.        In order to avoid having memory recovered while we are
  120.        manipulating pointers, we increment reference count, then change
  121.        pointers, then decrement reference counts */
  122.  
  123.     obj_inc((object *) currentProcess);
  124.     safeassign(currentProcess->prev, (process *) o_nil);
  125.     safeassign(currentProcess->next, (process *) o_nil);
  126.     obj_dec((object *) currentProcess);
  127. }
  128.  
  129.  
  130. /* link_to_process - change the interpreter for the current process */
  131. link_to_process (anInterpreter)
  132. interpreter  *anInterpreter;
  133. {    object *temp;
  134.  
  135.     safeassign(runningProcess->interp, anInterpreter);
  136. }
  137.  
  138.  
  139. /* remove_process - remove a process from process queue */
  140. static remove_process (aProcess)
  141. process  *aProcess;
  142. {
  143.     if (aProcess == aProcess->next)
  144.         cant_happen(15);        /* removing last active process */
  145.  
  146.     /* currentProcess must always point to a process that is on the
  147.        process queue, make sure this remains true */
  148.  
  149.     if (aProcess == currentProcess)
  150.         currentProcess = currentProcess->prev;
  151.  
  152.     /* In order to avoid having memory recovered while we are changing
  153.     pointers, we increment the reference counts on both processes,
  154.     change pointers, then decrement reference counts */
  155.  
  156.     obj_inc((object *) currentProcess); obj_inc((object *) aProcess);
  157.     safeassign(aProcess->next->prev, aProcess->prev);
  158.     safeassign(aProcess->prev->next, aProcess->next);
  159.     obj_dec((object *) currentProcess); obj_dec((object *) aProcess);
  160. }
  161.  
  162.  
  163. /* schedule_process - add a new process to the process queue */
  164. static schedule_process (aProcess)
  165. process  *aProcess;
  166. {
  167.     safeassign(aProcess->next, currentProcess);
  168.     safeassign(aProcess->prev, currentProcess->prev);
  169.     safeassign(aProcess->prev->next, aProcess);
  170.     safeassign(currentProcess->prev, aProcess);
  171. }
  172.  
  173. /* set_state - set the state on a process, which may involve inserting or
  174. removing it from the process queue */
  175. int  set_state (aProcess, state)
  176. process  *aProcess;
  177. int  state;
  178. {
  179.     switch (state) {
  180.         case BLOCKED:
  181.         case SUSPENDED:
  182.         case TERMINATED:    if (aProcess->p_state == ACTIVE)
  183.                     remove_process(aProcess);
  184.                 aProcess->p_state |= state;
  185.                 break;
  186.  
  187.         case READY:
  188.         case UNBLOCKED:    if ((aProcess->p_state ^ state) == ~ACTIVE)
  189.                     schedule_process(aProcess);
  190.                 aProcess->p_state &= state;
  191.                 break;
  192.  
  193.         case CUR_STATE:    break;
  194.         default:        cant_happen(17);
  195.         }
  196.     return(aProcess->p_state);
  197. }
  198.  
  199. # ifdef SETJUMP
  200. static jmp_buf intenv;
  201. # endif
  202.  
  203. /* brkfun - what to do on a break key */
  204. brkfun()
  205. {    static int warn = 1;
  206.  
  207. # ifndef SETJUMP
  208.     exit(1);
  209. # endif
  210.     if (warn) {
  211.         fprintf(stderr,"warning: recovery from interrupt may cause\n");
  212.         fprintf(stderr,"reference counts to be incorrect, and\n");
  213.         fprintf(stderr,"some memory to be inaccessible\n");
  214.         warn = 0;
  215.         }
  216. # ifdef SETJUMP
  217.     longjmp(intenv, 1);
  218. # endif
  219. }
  220.  
  221. /* start_execution - main execution loop */
  222. start_execution ()
  223. {    interpreter  *presentInterpreter;
  224.  
  225.     atomcnt = 0;
  226.  
  227. # ifdef SIGS
  228.     /* trap user interrupt signals and recover */
  229.     signal(SIGINT, brkfun);
  230. # endif
  231.  
  232. # ifdef SETJUMP
  233.     if (setjmp(intenv)) {
  234.         atomcnt = 0;
  235.         link_to_process(o_drive);
  236.         }
  237. # endif
  238.  
  239.     while (1) {
  240.         /* unless it is an atomic action get the next process */
  241.         if (! atomcnt)
  242.         runningProcess = currentProcess = currentProcess->next;
  243.  
  244.         if (! is_driver(runningProcess->interp)) {
  245.         sassign(presentInterpreter, runningProcess->interp);
  246.         resume(presentInterpreter);
  247.         obj_dec((object *) presentInterpreter);
  248.         }
  249.         else if (! test_driver((currentProcess == currentProcess->next) ||
  250.                    (atomcnt > 0)))
  251.         break;
  252.         }
  253. }
  254.